home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / Graphics / QuickDraw GX / GX->PostScript Sample / GXToPostScript / Imaging Engine / DrawShape.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  12.0 KB  |  424 lines  |  [TEXT/MPS ]

  1. /*
  2.      File:        DrawShape.c
  3.  
  4.      Contains:    QuickDraw GX to PostScript conversion code.
  5.                          File contains Main shape entry point for the Imaging Engine
  6.  
  7.      Version:    Technology:    Quickdraw GX 1.1.x
  8.       
  9.      Copyright:    © 1991-1997 by Apple Computer, Inc., all rights reserved.
  10. */
  11.  
  12. #include "GXToPSBuildConfig.h"
  13. #include <GXGraphics.h>
  14. #include "GXGraphicsPriv.h"
  15. #include <GXEnvironment.h>
  16. #include "GXToPostScript.h"
  17. #include "IOUtilities.h"
  18. #include "RDUtil.h"
  19. #include "FontHandler.h"
  20. #include "PublicPostScriptIE.h"
  21. #include "private.h"
  22. #include "PSIEResources.h"
  23. #include "GXErrors.h"
  24. #include "ProcessShape.h"
  25. #include "ShapeUtilities.h"
  26.  
  27.  
  28. #ifdef TIMEIE
  29.     #include "timer.h"
  30.     // 1 hour in milliseconds.
  31.     #define maxShapeTime 60 * 60 * 1000
  32. #endif
  33.  
  34. #ifdef resumeLabel
  35.     #undef resumeLabel
  36. #endif
  37. #define resumeLabel(exception)
  38.  
  39.  
  40. //<FF>
  41. /**********************************************************
  42.     Routine:    ShapeToPostScript
  43.     
  44.     Routine controls the translation of a shape into PostScript.
  45.     The shape must not be a picture or a QuickDraw Shape.
  46.     
  47.         context:            A valid PostScript Imaging Engine context.
  48.         theShape:            the shape to translate.
  49.         depth:                The depth of the shape in the picture hierarchy.
  50.         parents:            An array of transforms which describe the ancestory of the shape, 1st is root.
  51.         
  52.     
  53. ************************************************************/
  54. OSErr ShapeToPostScript(TPSIEContext context, gxShape theShape, gxTransform *parents, long depth);
  55. OSErr ShapeToPostScript(TPSIEContext context, gxShape theShape, gxTransform *parents, long depth)
  56.     {
  57.         OSErr                            status = noErr;
  58.         TIEGlobalsPtr            pGlobals;
  59.         long                            nSyn;
  60.         TRDParams                    rdParams;
  61.         TShapeStack                shapeStack;
  62.         gxShape                        aShape;
  63.         Boolean                        shapeIsPSContinuation = false;
  64.         
  65. #ifdef TIMEIE
  66.         TMTask            theTMTask;
  67. #endif
  68.  
  69. #ifdef testapp
  70.     gGlobalHdl = (TIEGlobalsHdl)context;
  71. #endif
  72.  
  73.     #ifdef lookAtShapeMapping
  74.         {
  75.             mapping        theMapping;
  76.             GetShapeMapping(theShape, &theMapping);
  77.             dprintf(notrace, "Shape Coming in: %X, Its Mapping:\n%M", theShape, &theMapping);
  78.         }
  79.     #endif            
  80.             
  81.         pGlobals = *(TIEGlobalsHdl)(context);            //    Dereference the context handle.
  82.  
  83.     #ifdef TIMEIE
  84.         theTMTask.qLink = 0;
  85.         theTMTask.qType = 0;
  86.         theTMTask.tmAddr = 0;
  87.         InsTime((QElemPtr)&theTMTask);
  88.         PrimeTime((QElemPtr)&theTMTask, maxShapeTime);
  89.         ++(pGlobals->shapeCount);
  90.     #endif
  91.  
  92.  
  93.         pGlobals->saveShape = theShape;                        //    Save the shape.
  94.         
  95.         /** Check the shape for synonyms **/
  96.  
  97.         nSyn = GXGetShapeTags(theShape, gxPostScriptTag, 1, gxSelectToEnd, nil);
  98.         
  99.         /** Only bother to image if the shape has synonyms or isn't noFill **/
  100.         
  101.         if ( (GXGetShapeFill(theShape) != gxNoFill ) || (nSyn > 0) ) {   // does shape draw anything?
  102.         
  103.             /*** Turn off text metric gridding so all text is in ideal space ***/
  104.             
  105.             GXSetShapeAttributes(theShape, GXGetShapeAttributes(theShape) | gxNoMetricsGridShape);
  106.             
  107.             /** If there are no synonyms, then make sure the shape is PostScriptable **/
  108.             
  109.             if (nSyn == 0) {
  110.             
  111.                 /* The PS continue next flag shouldn't be set if the current shape doesn't have synonym */
  112.                 
  113.                 ncheck ( (*(TIEGlobalsHdl)context)->ieStateFlags & ePSContinueNext );
  114.             
  115.                 /* We also ought not be getting pictures at this level */
  116.                 
  117.                 ncheck(TestShapeTypePict(theShape));
  118.     
  119.                 /** First make the Transform heiarchy PostScriptable **/
  120.     
  121.                 status = ResolveComplexTransform((TIEGlobalsHdl)context, parents, &depth, &theShape);
  122.                 nrequire(status, failed_ResolveComplexTransform);
  123.     
  124.                 /** Second, Make the shape/style combination PostScriptable **/
  125.                 
  126.                 status = ValidateFillShape((TIEGlobalsHdl)context, &theShape);
  127.                 nrequire(status, failed_Validate);
  128.     
  129.                 /** Third, Handle Large paths **/
  130.                 
  131.                 if (!TestShapeTypePict(theShape) || (nSyn > 0)) {    // Could have a picture from Vallidate.
  132.         
  133.                     nrequire(status = DissectShape((TIEGlobalsHdl)context, &theShape), failed_Split);
  134.                     
  135.                 } else {            // Walk picture.
  136.                 
  137.                     nrequire(status = TMNewStack(&shapeStack), failed_NewStack);
  138.                     nrequire(status = TMPushShape(&shapeStack, theShape), failed_DrawShape);
  139.         
  140.                     while (aShape = TMNextShape(&shapeStack)) {
  141.                     
  142.                         status = DissectShape((TIEGlobalsHdl)context, &aShape);
  143.                         nrequire(status, failed_Split);
  144.                                     
  145.                     }//end while
  146.                     
  147.                     TMDisposeStack(&shapeStack);        
  148.                 
  149.                 }//end if
  150.                 
  151.             } else {
  152.             
  153.                 /* Shape has a postscript synonym, see if it is a continuation of the last shape */
  154.  
  155.                 pGlobals = *(TIEGlobalsHdl)(context);            //    Dereference the context handle.
  156.                 
  157.                 shapeIsPSContinuation = (pGlobals->ieStateFlags & ePSContinueNext) ? true : false;
  158.                 
  159.             }//end if
  160.             
  161.             
  162.             pGlobals = *(TIEGlobalsHdl)(context);            //    Dereference the context handle.
  163.             
  164.             pGlobals->pRDParams = &rdParams;            // pointer to the param block on stack.
  165.                     
  166.             /**************
  167.                 Set up the res dump utility parameter block for usual case
  168.                 all lower level drones expect everything set here to be
  169.                 maintained.  If any drones change these fields, they must
  170.                 restore them before calling on to other drones or returning!!
  171.             ***************/
  172.     
  173.             rdParams.rdMap = pGlobals->rdMap;
  174.             rdParams.resType = kScriptResType;
  175.             rdParams.resID = kScriptResID;
  176.             rdParams.rdFlags = eRDCharSubs + eRDNoAutoFlush;
  177.             
  178.             status = pGlobals->psDevice->Idle();                    // DL 7/8/97
  179.             //nrequire(status = GXJobIdle(), failed_Idle);                    // Idle at least once per shape.
  180.     
  181.             if (!TestShapeTypePict(theShape) || (nSyn > 0)) {            // Could have a picture from PostScriptablizing the shape.
  182.                 
  183.                 /** If it is continuation postscript, just bypass the shape drone, call synonym drone - otherwise process it as normal shape **/
  184.                 
  185.                 if (shapeIsPSContinuation)
  186.                     nrequire(status = PostScriptSynonymDrone((TIEGlobalsHdl)context, theShape, nSyn), failed_Draw);
  187.                 else
  188.                     nrequire(status = ShapeDrone((TIEGlobalsHdl)context, theShape, parents, depth), failed_Draw);
  189.                 
  190.             } else {            // Walk picture and translate each shape.
  191.             
  192.                 nrequire(status = TMNewStack(&shapeStack), failed_NewStack);
  193.                 nrequire(status = TMPushShape(&shapeStack, theShape), failed_DrawShape);
  194.     
  195.                 while (aShape = TMNextShape(&shapeStack)) {
  196.                 
  197.                     status = ShapeDrone((TIEGlobalsHdl)context, aShape, parents, depth);
  198.                     nrequire(status, failed_DrawShape);
  199.                                 
  200.                 }//end while
  201.                 
  202.     failed_DrawShape:            
  203.                 TMDisposeStack(&shapeStack);        
  204.                         
  205.             }//end if
  206.     
  207.     failed_NewStack:
  208.     failed_Draw:
  209.     failed_Idle:        
  210.     
  211.             pGlobals = *(TIEGlobalsHdl)(context);            //    Dereference the context handle.
  212.             
  213.             /** Check to see if the shape changed, if it did dispose of the new one. **/
  214.     
  215.             if (pGlobals->saveShape != theShape)
  216.                 GXDisposeShape(theShape);
  217.             
  218.         }//end if (does shape draw anything?)
  219.  
  220. failed_Split:
  221. failed_Validate:
  222. failed_ResolveComplexTransform:
  223.  
  224.         if (status == noErr)
  225.             status = GXGetGraphicsError(nil);
  226.  
  227.     #ifdef TIMEIE
  228.         RmvTime((QElemPtr)&theTMTask);
  229.         pGlobals->shapeTime += maxShapeTime - theTMTask.tmCount;
  230.     #endif
  231.  
  232.         return(status);
  233.         
  234.     }//ShapeToPostScript
  235.  
  236.  
  237.  
  238. //<FF>
  239.  
  240. /*-----------------------------------------------------------------------*/
  241.  
  242. /** Structure for translator refcon for QD Pict Shapes **/
  243.  
  244. typedef struct {
  245.  
  246.     OSErr                            status;
  247.     TPSIEContext            context;                    // Imaging Engine context.
  248.     gxTransform                *parents;                    // parent transform list.
  249.     long                            depth;                        // transform list depth.
  250.  
  251. } TIEqdTranslation;
  252.  
  253. /*********************************************
  254.  
  255.     Callback for imaging QuickDraw Pict shapes.
  256.     
  257. **********************************************/
  258. gxGraphicsError PSTranslationCallBack(gxShape theShape, long refCon);
  259. gxGraphicsError PSTranslationCallBack(gxShape theShape, long refCon)
  260.     {
  261.         TIEqdTranslation    *qdTranslation = (TIEqdTranslation*)refCon;
  262.     
  263.         qdTranslation->status = ShapeToPostScript(qdTranslation->context, theShape, qdTranslation->parents, qdTranslation->depth);        
  264.         ncheck(qdTranslation->status);
  265.         
  266.         if (qdTranslation->status != noErr)
  267.             return(1);            // just non-zero value
  268.         else
  269.             return(0);
  270.             
  271.     }//TranslationCallBack
  272.  
  273.  
  274. //<FF>
  275. #if DEBUGLEVEL > 2
  276. //    #define DRAWSHAPESONSCREEN
  277. #endif
  278.  
  279. #ifdef DRAWSHAPESONSCREEN
  280. void DEBUGDrawShapeOnScreen(gxShape theShape, gxTransform *parents, long depth)
  281.     {
  282.         long                i;        
  283.         gxShape            thePicture[26];    
  284.     
  285.         check(depth <= 25);
  286.  
  287.         /** Build a picture heirarchy to reflect the parents **/
  288.         
  289.         thePicture[0] = GXNewShape(gxPictureType);                // Create a root level picture.
  290.         
  291.         for (i = 0; i < depth; ++i) {
  292.  
  293.             thePicture[i+1] = GXNewShape(gxPictureType);
  294.             GXSetShapeTransform(thePicture[i+1], parents[i]);
  295.             
  296.             GXSetPictureParts(thePicture[i], 1, 0, 1, &(thePicture[i+1]), nil, nil, nil);
  297.         
  298.         }//end of
  299.         
  300.         /* Add the shape to the heirarchy */
  301.         
  302.         GXSetPictureParts(thePicture[depth], 1, 0, 1, &theShape, nil, nil, nil);
  303.         
  304.         GXDrawShape(thePicture[0]);
  305.         
  306.         for (i = 0; i <= depth; ++i) {
  307.  
  308.             GXDisposeShape(thePicture[i]);
  309.         
  310.         }//end of
  311.  
  312.     }//DEBUGDrawShapeOnScreen
  313.  
  314. #endif
  315.  
  316.  
  317. /**********************************************************
  318.     Routine:    PostScriptDrawShape
  319.     
  320.     Routine controls the translation of a shape into PostScript.
  321.     This is the root level call for a GX shape.  Routine will
  322.     handle the translation of QuickDraw shapes.
  323.     
  324.         context:            A valid PostScript Imaging Engine context.
  325.         theShape:            the shape to translate.
  326.         depth:                The depth of the shape in the picture hierarchy.
  327.         parents:            An array of transforms which describe the ancestory of the shape, 1st is root.
  328.         
  329.     
  330. ************************************************************/
  331. OSErr PostScriptDrawShape(TPSIEContext context, gxShape theShape, gxTransform *parents, long depth)
  332.     {
  333.         OSErr                                            status;
  334.         gxShapeType                                theType;
  335.         
  336.         #ifdef DRAWSHAPESONSCREEN
  337.             DEBUGDrawShapeOnScreen(theShape, parents, depth);
  338.             //return(noErr);
  339.         #endif
  340.  
  341.         theType = QGXGetShapeType(theShape);
  342.         
  343.         if (theType != gxQuickDrawPictType) {
  344.         
  345.             status = ShapeToPostScript(context, theShape, parents, depth);
  346.             nrequire(status, failed_shape);
  347.             
  348.         } else {
  349.         
  350.             TIEqdTranslation                    qdTranslation;
  351.             gxTranslationStatistic        stats;
  352.             gxTransform                                theTransform = GXGetShapeTransform(theShape);
  353.             gxMapping                                    aMapping;
  354.             gxTransform                                *newParents = nil;
  355.     
  356.             #if GENERATINGPOWERPC
  357.                 RoutineDescriptor            callBackDesc = BUILD_ROUTINE_DESCRIPTOR(uppgxShapeSpoolProcInfo, PSTranslationCallBack);
  358.                 gxShapeSpoolUPP                uppPSTranslationCallBack = (gxShapeSpoolUPP) &callBackDesc;
  359.             #else
  360.                 gxShapeSpoolUPP                uppPSTranslationCallBack = (gxShapeSpoolUPP) PSTranslationCallBack;
  361.             #endif
  362.  
  363.             qdTranslation.context = context;
  364.  
  365.             /**************
  366.  
  367.                 Invoke translation of QuickDraw PICT shape and image one at a time.
  368.                 
  369.                 Our Translation refcon will be a pointer to a structure containing parameters
  370.                 necessary to pass to ShapeToPostScript.
  371.                 
  372.                 If the transform of the QuickDraw shape is identity then we can just pass the original
  373.                 transform list through.  If it is not, we must add it to the transform list so that
  374.                 shapes generated by the translator will draw through the QD shape's transform
  375.                 as well as the ones that are in the transform list.
  376.                 
  377.             ***************/
  378.  
  379.             if ( TestMappingIdentity(GXGetTransformMapping(theTransform, &aMapping) ) &&
  380.                       (GetTransformClipType(theTransform) == gxFullType) ) {
  381.                         
  382.                 qdTranslation.parents = parents;
  383.                 qdTranslation.depth = depth;
  384.                 
  385.             } else {
  386.             
  387.                 /* Make new parent transform list, 1 bigger to hold QD shape's transform */
  388.                 
  389.                 status = PrNewPtr((Ptr*)&newParents, (depth + 1) * sizeof(gxTransform));
  390.                 nrequire(status, failed_newPtr);
  391.                 
  392.                 BlockMove((Ptr)parents, (Ptr)newParents, depth * sizeof(gxTransform));
  393.                 newParents[depth] = theTransform;
  394.                 qdTranslation.parents = newParents;
  395.                 qdTranslation.depth = depth + 1;
  396.             
  397.             }//end if
  398.         
  399.             qdTranslation.status = noErr;
  400.             status = QGXTranslateQuickDrawPict(theShape, uppPSTranslationCallBack, (long)&qdTranslation, &stats);
  401.             if (status == noErr)
  402.                 status = qdTranslation.status;
  403.             
  404.             if (newParents != nil)
  405.                 DisposePtr((Ptr)newParents);
  406.         }//end if
  407.         
  408.         /** Flush the RDUtilities Buffer per shape in case extension is using BufferData **/
  409.                 
  410.         status = RDFlushBuffer((*(TIEGlobalsHdl)context)->rdMap);
  411.         ncheck(status);
  412.  
  413. failed_newPtr:
  414. failed_shape:    
  415.  
  416.         return(status);
  417.     
  418.     }//PostScriptDrawShape
  419.  
  420.  
  421.  
  422.  
  423.  
  424.